package com.xiao.tripmateai.agent;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions;
import com.xiao.tripmateai.agent.model.AgentState;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.messages.*;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.prompt.ChatOptions;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.model.tool.ToolCallingManager;
import org.springframework.ai.model.tool.ToolExecutionResult;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.ai.tool.ToolCallbackProvider;

import java.util.List;
import java.util.stream.Collectors;

/**
 * ToolCallAgent类 - 继承自ReActAgent，用于处理AI模型的工具调用
 * 实现了思考(think)和行动(act)两个核心方法，处理工具调用流程
 */
@EqualsAndHashCode(callSuper = true)
@Data
@Slf4j
public class ToolCallAgent extends ReActAgent {

    // 存储AI模型返回的包含工具调用信息的聊天响应
    private ChatResponse toolCallChatResponse;
    // 工具调用管理器，负责执行工具调用
    private final ToolCallingManager toolCallingManager;
    // 聊天配置选项
    private final ChatOptions chatOptions;
//    // 组合工具回调提供者
//    private ToolCallbackProvider combinedToolCallbackProvider;

    /**
     * 构造函数，初始化工具调用管理器和聊天选项
     */
    public ToolCallAgent() {
        // 构建默认的工具调用管理器
        this.toolCallingManager = ToolCallingManager.builder().build();
        // 配置DashScope聊天选项，禁用内部工具执行
        this.chatOptions = DashScopeChatOptions.builder()
                .withInternalToolExecutionEnabled(false)
                .build();
    }

    /**
     * 思考方法 - 分析问题并决定是否需要调用工具
     * @param publisher 用于发布处理事件的发布器
     * @return 如果需要调用工具返回true，否则返回false
     */
    @Override
    public boolean think(SSEPublisher publisher) {
        try {
            // 1. 准备提示词
            if (StrUtil.isNotBlank(getNextStepPrompt())) {
                // 精简提示词日志，避免暴露过多细节
                publisher.publish(EVENT_THINKING, "添加下一步提示");
                getMessageList().add(new UserMessage(getNextStepPrompt()));
            }

            // 2. 调用AI模型
            List<Message> messages = getMessageList();
            Prompt prompt = new Prompt(messages, this.chatOptions);

            publisher.publish(EVENT_THINKING, "调用AI模型分析...");
            ChatResponse chatResponse = getChatClient().prompt(prompt)
                    .system(getSystemPrompt())
                    .call()
                    .chatResponse();

            // 保存模型响应并获取助手消息
            this.toolCallChatResponse = chatResponse;
            AssistantMessage assistantMessage = chatResponse.getResult().getOutput();
            String thoughtProcess = assistantMessage.getText();

            // 3. 精简思考过程输出
            publisher.publish(EVENT_THINKING, "分析结论: " + thoughtProcess);

            // 4. 分析工具调用
            List<AssistantMessage.ToolCall> toolCallList = assistantMessage.getToolCalls();
            if (toolCallList.isEmpty()) {
                publisher.publish(EVENT_THINKING, "决策: 无需调用工具");
                getMessageList().add(assistantMessage);
                return false;
            }

            // 5. 组织工具调用信息
            StringBuilder toolsInfo = new StringBuilder();
            toolsInfo.append("决策: 需要调用 ").append(toolCallList.size()).append(" 个工具\n");

            for (AssistantMessage.ToolCall tool : toolCallList) {
                String toolName = tool.name();
                String arguments = tool.arguments();

                // 发送工具调用事件
                publisher.publish(EVENT_ACTION, "工具调用: " + toolName);

                // 添加到工具信息
                toolsInfo.append("- ").append(toolName);
                toolsInfo.append(": ").append(arguments).append("\n");
            }

            publisher.publish(EVENT_THINKING, toolsInfo.toString());
            return true;
        } catch (Exception e) {
            publisher.publish(EVENT_ERROR, "思考过程出错: " + e.getMessage());
            getMessageList().add(new AssistantMessage("思考过程出错: " + e.getMessage()));
            return false;
        }
    }

    /**
     * 行动方法 - 执行工具调用并处理结果
     * @param publisher 用于发布处理事件的发布器
     * @return 工具执行状态信息
     */
    @Override
    public String act(SSEPublisher publisher) {
        try {
            StringBuilder resultSummary = new StringBuilder();

            // 1. 检查工具调用
            if (!toolCallChatResponse.hasToolCalls()) {
                publisher.publish(EVENT_RESULT, "没有工具需要调用");
                return "无工具调用";
            }

            // 2. 执行工具调用
            publisher.publish(EVENT_ACTION, "执行工具调用...");
            Prompt prompt = new Prompt(getMessageList(), this.chatOptions);
            ToolExecutionResult toolExecutionResult = toolCallingManager.executeToolCalls(
                    prompt, toolCallChatResponse);

            // 更新消息列表
            setMessageList(toolExecutionResult.conversationHistory());
            ToolResponseMessage toolResponseMessage =
                    (ToolResponseMessage) CollUtil.getLast(toolExecutionResult.conversationHistory());

            // 3. 处理结果
            boolean terminateToolCalled = false;
            StringBuilder toolResults = new StringBuilder();

            for (ToolResponseMessage.ToolResponse response : toolResponseMessage.getResponses()) {
                String toolName = response.name();
                String responseData = response.responseData();

                // 检查是否调用了终止工具
                if ("doTerminate".equals(toolName)) {
                    terminateToolCalled = true;
                }

                // 精简工具结果输出
                String abbreviatedResult = responseData;
                String toolResultMsg = toolName + ": " + abbreviatedResult;

                // 发送工具结果事件
                publisher.publish(EVENT_RESULT, toolResultMsg);

                // 添加到结果摘要
                toolResults.append("- ").append(toolResultMsg).append("\n");
            }

            // 4. 如果调用了终止工具，设置代理状态为已完成
            if (terminateToolCalled) {
                setState(AgentState.FINISHED);
                publisher.publish(EVENT_FINISHED, "检测到终止工具调用");
                resultSummary.append("任务终止");
            } else {
                resultSummary.append("工具执行完成");
            }

            // 记录工具调用结果
            log.info("工具调用结果: {}", toolResults);
            return resultSummary.toString();
        } catch (Exception e) {
            publisher.publish(EVENT_ERROR, "执行失败: " + e.getMessage());
            return "执行错误: " + e.getMessage();
        }
    }

    /**
     * 精简长文本，添加省略号
     *
     * @param text 原始文本
     * @param maxLength 最大长度
     * @return 精简后的文本
     */
    private String abbreviate(String text, int maxLength) {
        if (StrUtil.isBlank(text)) {
            return "";
        }

        if (text.length() <= maxLength) {
            return text;
        }

        return text.substring(0, maxLength) + "...";
    }
}